package com.juyu.miliao.api.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.juyu.miliao.api.config.SegmentedLockManager;
import com.juyu.miliao.api.constant.DepositType;
import com.juyu.miliao.api.dao.mysql.*;
import com.juyu.miliao.api.dao.redis.BuyPrivateRedisDao;
import com.juyu.miliao.api.dao.redis.DiamondRedisDao;
import com.juyu.miliao.api.dao.redis.UserRedisDao;
import com.juyu.miliao.api.domain.*;
import com.juyu.miliao.api.domain.dto.IntegralLevelAndTitleDTO;
import com.juyu.miliao.api.exception.WrongNoDepositException;
import com.juyu.miliao.api.handler.UserInvitationIncomeDetailsHandler;
import com.juyu.miliao.api.util.SystemMessageUtil;
import com.juyu.miliao.common.constant.SpendSystemMessage;
import com.juyu.miliao.common.constant.SpendSystemMessageType;
import com.juyu.miliao.common.netease.NetEaseCloudUserService;
import com.juyu.miliao.common.util.DoubleFormatUtil;
import com.juyu.miliao.common.exception.ConsumeRuntimeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.juyu.miliao.common.msg.CommonErrorMsgs.*;

@Service
public class PrivatePhotoService {
    private final Logger logger = LoggerFactory.getLogger(PrivatePhotoService.class);
    @Resource
    private PrivatePhotoDao privatePhotoDao;
    @Resource
    private UserCountDao userCountDao;
    @Resource
    private UserWalletDao userWalletDao;
    @Resource
    private BillDetailDao billDetailDao;
    @Resource
    private BuyPrivateRedisDao buyPrivateRedisDao;
    @Resource
    private RedisTemplateService redisTemplateService;
    @Resource
    private AppKeyService appkeyService;
    @Resource
    private UserRedisDao userRedisDao;
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private IntegralLevelInfoService integralLevelInfoService;
    @Resource
    private DiamondRedisDao diamondRedisDao;
    @Resource
    private SystemMessageUtil systemMessageUtil;

    @Resource
    private UserInvitationIncomeDetailsHandler userInvitationIncomeDetailsHandler;
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private SegmentedLockManager segmentedLockManager;

    public List<UserPhoto> getPrivatePhotoById(long id, long tokenId) {

        List<UserPhoto> userPhoto = privatePhotoDao.getPrivatePhotoById(id);

        //如果是看自己的私照都显示为以购买
        if (tokenId == id) {
            userPhoto.forEach(i -> {
                i.setIsBuy(1);
                i.setPicBuyNum(buyPrivateRedisDao.getPicBuyNum(i.getPrivateId()));
            });
            return userPhoto;
        } else {//如果是别人查看私照，则要判断查看的用户是否购买过该照片
            List<UserPhoto> otherUserCanSeePonto = new ArrayList<>();
            userPhoto.forEach(i -> {
                if (i.getPicState() == 1) {
                    if (i.getPicType() == 2) {
                        if (buyPrivateRedisDao.isExist(tokenId, i.getPrivateId())) {
                            i.setIsBuy(1);
                        }
                        i.setPicBuyNum(buyPrivateRedisDao.getPicBuyNum(i.getPrivateId()));
                    }
                    otherUserCanSeePonto.add(i);
                }
            });
            return otherUserCanSeePonto;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void deletePrivatePhoto(int userId, int privateId) {
        int result = privatePhotoDao.deletePrivatePhotoById(privateId, userId);
        if (result == 1) {
            User user = userInfoDao.getUserInfoById(userId);
            userCountDao.reducePrivateSum(userId);
            buyPrivateRedisDao.deletePrivateByPrivateId(privateId);
            if (user.getIsHost() == 1) {
                userRedisDao.deleteUserCheckPriUrlForHost(privateId);
            } else {
                userRedisDao.deleteUserCheckPriUrl(privateId);
            }

        } else {
            throw new ConsumeRuntimeException(COMMON_DELETE_ERROR);
        }
    }

    public UserPhoto addPrivatePhoto(UserPhoto entity) {
        int result = privatePhotoDao.insertPrivatePhoto(entity);
        if (result == 1) {
            entity.setIsBuy(1);
            //添加成功后 redis 中 添加用户id
            if (entity.getPicUrl() != null) {
                User user = userInfoDao.getUserInfoById((int) entity.getUserId());
                if (user.getIsHost() == 1) {
                    userRedisDao.userInfoCheckPriUrlForHost(entity.getPrivateId());
                } else {
                    userRedisDao.userInfoCheckPriUrl(entity.getPrivateId());
                }
            }
            return entity;
        }
        throw new ConsumeRuntimeException(COMMON_SAVE_ERROR);
    }


    @Transactional(rollbackFor = Exception.class)
    public List<UserPhoto> batchAddPrivatePhoto(UserPhoto entity) {
        if (entity.getPicUrl() != null && !entity.getPicUrl().equals("")) {
            if (entity.getPicType() == 2) {
                List<UserPhoto> list = privatePhotoDao.getFreePhotoByUserId(entity.getUserId());
                if (list.size() < 3) {
                    throw new ConsumeRuntimeException(SEND_FREE_PHOTO_TO_PRIVITE);
                }
            }
            List<UserPhoto> tempList = new ArrayList<UserPhoto>();
            if (entity.getPicType() == 0) {
                entity.setPicType(2);
            } else {
                entity.setPicType(entity.getPicType());
            }
            if (entity.getPicUrl().contains(",")) {
                String[] array = entity.getPicUrl().split(",");
                for (int i = 0; i < array.length; i++) {
                    UserPhoto temp = new UserPhoto();
                    temp.setUserId(entity.getUserId());
                    temp.setPicUrl(array[i]);
                    temp.setIsBuy(1);
                    temp.setPicType(entity.getPicType());
                    temp.setPicState(2);
                    privatePhotoDao.insertPrivatePhoto(temp);
                    userCountDao.addPrivateSum(entity.getUserId());
                    tempList.add(temp);
                    //批量添加成功之后 redis 中 添加用户id
                    if (entity.getPicUrl() != null) {
                        User user = userInfoDao.getUserInfoById((int) entity.getUserId());
                        if (user.getIsHost() == 1) {
                            userRedisDao.userInfoCheckPriUrlForHost(temp.getPrivateId());
                        } else {
                            userRedisDao.userInfoCheckPriUrl(temp.getPrivateId());
                        }
                    }
                }
            } else {
                entity.setPicState(2);
                int result = privatePhotoDao.insertPrivatePhoto(entity);
                if (result == 1) {
                    userCountDao.addPrivateSum(entity.getUserId());
                    entity.setIsBuy(1);
                    //    User user = userInfoDao.getUserById(entity.getUserId());
                    if (entity.getPicUrl() != null) {
                        User user = userInfoDao.getUserInfoById((int) entity.getUserId());
                        if (user.getIsHost() == 1) {
                            userRedisDao.userInfoCheckPriUrlForHost(entity.getPrivateId());
                        } else {
                            userRedisDao.userInfoCheckPriUrl(entity.getPrivateId());
                        }
                    }
                    tempList.add(entity);
                    return tempList;
                } else {
                    throw new ConsumeRuntimeException(COMMON_SAVE_ERROR);
                }
            }
            return tempList;
        } else {
            throw new ConsumeRuntimeException(COMMON_SAVE_ERROR);
        }
    }


    /**
     * 购买私照
     */
    @Transactional(rollbackFor = Exception.class)
    public void buyPrivatePhoto(int buyUserId, int privateId) {
        //判断是否重复购买
        if(buyPrivateRedisDao.hasKeyBuyChatPhoto(buyUserId+""+privateId)){
            throw new WrongNoDepositException("重复购买");
        }
        //判断buyUser金币够不够
        UserWallet userWallet = userWalletDao.getUserWalletById(buyUserId);
        //获取照片价格
        Appkey privatePhotoAppKey = appkeyService.getAppKeyByKey("privatePhoto");
        int privatePhotoPrice = Integer.parseInt(privatePhotoAppKey.getValue());
        //获取金币转换钻石比例
        //  Appkey giftRatioKey = appkeyService.getAppKeyByKey("giftRatio");

        //  double giftRatio = Double.parseDouble(giftRatioKey.getValue());
        //金币不够抛出异常
        if (privatePhotoPrice > userWallet.getDeposit()) {
            throw new WrongNoDepositException("寻币不足");
        }
        //消费者,修改剩余金币
        userWallet.setDeposit(privatePhotoPrice);
        int num = userWalletDao.minusDeposit(userWallet);
        if (num != 1) {
            throw new WrongNoDepositException("金币不足");
        }
        //收款者，修改剩余钻石
        //如果够，先通过privateId查出userId，对用户钱包表进行操作，buyUserId减金币 userId加钻石
        UserPhoto userPhoto = privatePhotoDao.getPrivatePhotoByPrivateId(privateId);
        //获取金币转换钻石比例
        User hostUser = userInfoDao.selectAdminByUnionId(userPhoto.getUserId());
        IntegralLevelAndTitleDTO integralLevelAndTitleDTO = integralLevelInfoService.getUserIntegralLevel(hostUser.getIntegralSum());
        double giftRatio = Double.parseDouble(integralLevelAndTitleDTO.getDiamondConversionRate() + "");
        UserWallet inUserWallet = new UserWallet();
        inUserWallet.setUserId(userPhoto.getUserId());
        //金币转换钻石
        double diamond = DoubleFormatUtil.doubleFormate(privatePhotoPrice * giftRatio);
        inUserWallet.setDiamond(diamond);
        userWalletDao.reviseDiamond(inUserWallet);

        //保存消费记录
        BillDetailDeposit billDetailDeposit = new BillDetailDeposit();
        billDetailDeposit.setOutUserId(buyUserId);
        billDetailDeposit.setSpend(-privatePhotoPrice);
        billDetailDeposit.setInUserId(userPhoto.getUserId());
        billDetailDeposit.setDiamond(diamond);
        billDetailDeposit.setRatio(giftRatio);
        if (hostUser != null) {
            billDetailDeposit.setUnionId(hostUser.getUnionId());
            billDetailDeposit.setAgentId(hostUser.getAgentId());
            billDetailDeposit.setAdminId(hostUser.getAdminId());
        }

        billDetailDeposit.setRecordType(DepositType.BUY_PRIVATE_PHOTO.getCode());
        billDetailDao.insertBillDetailDeposit(billDetailDeposit);
//        BillDetail billDetail = new BillDetail();
//        billDetail.setInUserId(userPhoto.getUserId());
//        billDetail.setOutUserId(buyUserId);
//        billDetail.setRecordType(1);
//        billDetail.setDiamond(diamond);
//        billDetail.setSpend(privatePhotoPrice);
//        billDetailDao.insertBillDetail(billDetail);
        //保存购买私照记录
        buyPrivateRedisDao.insertBuyPrivate(buyUserId, privateId);
        //邀请分成
        userInvitationIncomeDetailsHandler.incomeDiamondsDetails(userPhoto.getUserId(), DepositType.BUY_PRIVATE_PHOTO.getCode(),
                new BigDecimal(diamond + ""));
        //用户统计m值
        userCountDao.addMGradeSum(billDetailDeposit.getInUserId(), billDetailDeposit.getDiamond());
        //用户统计v值(6.19-土豪值只从充值和获取金币处计算)
//		userCountDao.addVGradeSum(billDetail.getOutUserId(), billDetail.getSpend());
        //排行榜统计(6.19-土豪值只从充值和获取金币处计算)
        redisTemplateService.setMUserSort(billDetailDeposit.getInUserId(), billDetailDeposit.getDiamond());
//		redisTemplateService.setVUserSort(billDetail.getOutUserId(), billDetail.getSpend());
        //发送系统消息 "xx消费了" +privatePhotoPrice+"寻币"+"查看了您的收费私照"
//        systemMessageUtil.sendSystemMessage(userPhoto.getUserId(),msg2);
        User buyUser = userInfoDao.getUserInfoById(buyUserId);
        String message = SpendSystemMessage.BUY_PRIVATE_PHOTO_SEND_MESSAGE.getMessage(buyUser.getNickName());
        String[] colorsArgs = {"#fd67c9"};
        String[] args = {buyUser.getNickName()};
        Map<String, Object> ext = new HashMap<>(1);
        ext.put("template", SpendSystemMessage.BUY_PRIVATE_PHOTO_SEND_MESSAGE.getMessage());
        ext.put("templateValue", args);
        ext.put("templateColors", colorsArgs);
        ext.put("userId", buyUserId);
        getSendMsg(userPhoto.getUserId(), message, SpendSystemMessageType.JUMP_TEXT_TYPE.getCode(), ext);
//        JSONObject body = new JSONObject();
//        String msg2 ="对方消费了" +privatePhotoPrice+"寻币"+"查看了您的收费私照";
//        body.put("msg", msg2);
//        JSONObject ext = new JSONObject();
//        //发送给主播用户
//        try {
//            String temp = NetEaseCloudUserService.getSendMsg((long)userPhoto.getUserId(), (long)buyUserId,
//                    EnumType.TEXT_MESSAGE.state, body.toString(), ext.toString(), "");
//            if (!temp.substring(temp.indexOf("code") + 6, temp.indexOf("code") + 9).equals("200")) {
//                logger.error("发送普通消息异常-云信：userId={},message={}", userPhoto.getUserId(), temp);
//            }
//        } catch (Exception e) {
//            logger.error("发送普通消息异常：userId={},error={}", userPhoto.getUserId(), e);
//        }
        buyPrivateRedisDao.setBuyChatPhoto(buyUserId+""+privateId);
    }

    public String getSendMsg(long userId, String message, String type, Map<String, Object> ext) {
        String createLogInfo = "";
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("title", "寻寻");
            map.put("type", type);
            map.put("message", message);
            map.put("ext", ext);
            createLogInfo = NetEaseCloudUserService.getSystemMessage(objectMapper.writeValueAsString(map), userId);
        } catch (Exception e) {
            e.getMessage();
        }
        return createLogInfo;
    }

    /**
     * 购买聊天付费闪图
     */
    @Transactional(rollbackFor = Exception.class)
    public void buyChatPhoto(int buyUserId, int inUserId, int type) {
        segmentedLockManager.sync(buyUserId + "", () -> {
            //判断是否重复购买
            if(buyPrivateRedisDao.hasKeyBuyChatPhoto(buyUserId+""+inUserId+""+type)){
                throw new WrongNoDepositException("重复购买");
            }
            //判断buyUser金币够不够
            UserWallet userWallet = userWalletDao.getUserWalletById(buyUserId);
            Appkey chatAppKey = new Appkey();
            if (type == 1) {
                //获取照片价格
                chatAppKey = appkeyService.getAppKeyByKey("chatPhoto");
            } else if (type == 2) {
                //获取语音价格
                chatAppKey = appkeyService.getAppKeyByKey("chatVoice");
            } else if (type == 3) {
                chatAppKey = appkeyService.getAppKeyByKey("chatVideo");
            }
            int chatPrice = Integer.parseInt(chatAppKey.getValue());
            //获取金币转换钻石比例
//        Appkey giftRatioKey = appkeyService.getAppKeyByKey("giftRatio");
//        double giftRatio = Double.parseDouble(giftRatioKey.getValue());
            //金币不够抛出异常
            if (chatPrice > userWallet.getDeposit()) {
                throw new WrongNoDepositException("寻币不足");
            }
            //消费者,修改剩余金币
            userWallet.setDeposit(chatPrice);
            int num = userWalletDao.minusDeposit(userWallet);
            if (num != 1) {
                throw new WrongNoDepositException("金币不足");
            }
            User hostUser = userInfoDao.selectAdminByUnionId(inUserId);
            IntegralLevelAndTitleDTO integralLevelAndTitleDTO = integralLevelInfoService.getUserIntegralLevel(hostUser.getIntegralSum());
            double giftRatio = Double.parseDouble(integralLevelAndTitleDTO.getDiamondConversionRate() + "");
            //收款者，修改剩余钻石
            UserWallet inUserWallet = new UserWallet();
            inUserWallet.setUserId(inUserId);
            //金币转换钻石
            double diamond = DoubleFormatUtil.doubleFormate(chatPrice * giftRatio);
            inUserWallet.setDiamond(diamond);
            userWalletDao.reviseDiamond(inUserWallet);
//        //保存消费记录
//        BillDetail billDetail = new BillDetail();
//        billDetail.setInUserId(inUserId);
//        billDetail.setOutUserId(buyUserId);
//        if(type == 1){
//            billDetail.setRecordType(RecordTypeEnum.HONEY_PHOTO.state);
//        }else if(type == 2){
//            billDetail.setRecordType(RecordTypeEnum.VOICE.state);
//        }else if(type == 3){
//            billDetail.setRecordType(RecordTypeEnum.HONEY_VIDEO.state);
//        }
//        billDetail.setDiamond(diamond);
//        billDetail.setSpend(chatPrice);
//        billDetailDao.insertBillDetail(billDetail);
            //保存消费记录
            BillDetailDeposit billDetailDeposit = new BillDetailDeposit();
            billDetailDeposit.setOutUserId(buyUserId);
            billDetailDeposit.setSpend(-chatPrice);
            billDetailDeposit.setInUserId(inUserId);
            billDetailDeposit.setDiamond(diamond);
            billDetailDeposit.setRatio(giftRatio);
            if (hostUser != null) {
                billDetailDeposit.setUnionId(hostUser.getUnionId());
                billDetailDeposit.setAgentId(hostUser.getAgentId());
                billDetailDeposit.setAdminId(hostUser.getAdminId());
            }
            if (type == 1) {
                billDetailDeposit.setRecordType(DepositType.BUY_HONEY_PHOTO_GET_COIN.getCode());
            }

            billDetailDao.insertBillDetailDeposit(billDetailDeposit);

            userInvitationIncomeDetailsHandler.incomeDiamondsDetails(inUserId, DepositType.BUY_HONEY_PHOTO_GET_COIN.getCode(),
                    new BigDecimal(diamond + ""));
//        用户统计m值
//      userCountDao.addMGradeSum(billDetail.getInUserId(), billDetail.getDiamond());
//      用户统计v值(6.19-土豪值只从充值和获取金币处计算)
//		userCountDao.addVGradeSum(billDetail.getOutUserId(), billDetail.getSpend());
//       排行榜统计(6.19-土豪值只从充值和获取金币处计算)
//       redisTemplateService.setMUserSort(billDetail.getInUserId(), billDetail.getDiamond());
//		redisTemplateService.setVUserSort(billDetail.getOutUserId(), billDetail.getSpend());
            //钻石排行榜统计主播赚取钻石
            diamondRedisDao.setRankingDiamondList(LocalDate.now(),
                    DoubleFormatUtil.doubleFormate(diamond), inUserId + "");

//        JSONObject body2 = new JSONObject();
//        JSONObject body4 = new JSONObject();
//        //开发者扩展字段
//        JSONObject ext = new JSONObject();
            if (type == 1) {
                User buyUser = userInfoDao.getUserInfoById(buyUserId);
                String message = SpendSystemMessage.BUY_PRIVATE_PHOTO_SEND_MESSAGE.getMessage(buyUser.getNickName());
                String[] colorsArgs = {"#fd67c9"};
                String[] args = {buyUser.getNickName()};
                Map<String, Object> ext = new HashMap<>(1);
                ext.put("template", SpendSystemMessage.BUY_PRIVATE_PHOTO_SEND_MESSAGE.getMessage());
                ext.put("templateValue", args);
                ext.put("templateColors", colorsArgs);
                ext.put("userId", buyUserId);
                getSendMsg(inUserId, message, SpendSystemMessageType.JUMP_TEXT_TYPE.getCode(), ext);
//            body2.put("msg", msg2);
//
//            //发送给主播用户
//            try {
//                String temp = NetEaseCloudUserService.getSendMsg((long)inUserId, (long)buyUserId,
//                        EnumType.TEXT_MESSAGE.state, body2.toString(), ext.toString(), "");
//                if (!temp.substring(temp.indexOf("code") + 6, temp.indexOf("code") + 9).equals("200"))
//                        logger.error("发送普通消息异常-云信：userId={},message={}", inUserId, temp);
//            } catch (Exception e) {
//                logger.error("发送普通消息异常：userId={},error={}", inUserId, e);
//            }
            } else if (type == 3) {
                // 发送购买视频通知
                String msg4 = "对方消耗了" + chatPrice + "寻币" + "查看了您的收费视频";
                systemMessageUtil.sendSystemMessage((long) inUserId, msg4);
//            body4.put("msg", msg4);
//            //发送给主播用户
//            try {
//                String temp = NetEaseCloudUserService.getSendMsg((long)inUserId, (long)buyUserId,
//                        EnumType.TEXT_MESSAGE.state, body4.toString(), ext.toString(), "");
//                if (!temp.substring(temp.indexOf("code") + 6, temp.indexOf("code") + 9).equals("200"))
//                    logger.error("发送普通消息异常-云信：userId={},message={}", inUserId, temp);
//            } catch (Exception e) {
//                logger.error("发送普通消息异常：userId={},error={}", inUserId, e);
//            }
            }
            buyPrivateRedisDao.setBuyChatPhoto(buyUserId+""+inUserId+""+type);
        });
    }

    /**
     * 设置私密或公开
     *
     * @param picType
     * @param privateId
     */
    public void updatePrivatePhotoPicType(int picType, int privateId) {
        privatePhotoDao.updatePrivatePhotoByPicType(picType, privateId);
    }


    /**
     * 设置封面
     *
     * @param userId
     * @param privateId
     */
    public void updateUserCoverUrl(long userId, int privateId) {
        //获取到私照对象
        UserPhoto userPhoto = privatePhotoDao.getPrivatePhotoByPrivateId(privateId);
        userInfoService.updateUserCoverUrl(userId, userPhoto.getPicUrl());

    }
}
